#include "buffer.h"

Buffer::Buffer(int initBuffSize) : buffer_(initBuffSize), readPos_(0), writePos_(0) {} 

size_t Buffer::ReadableBytes() const { //获取未读字节数
    return writePos_ - readPos_;
}
size_t Buffer::WritableBytes() const { //获取可写字节数
    return buffer_.size() - writePos_;
}

size_t Buffer::PrependableBytes() const {  //已经完成读取（解析）的字节数
    return readPos_;
}

const char* Buffer::Peek() const { //获取读取（解析）起点
    return BeginPtr_() + readPos_;
}

void Buffer::Retrieve(size_t len) {
    assert(len <= ReadableBytes());
    readPos_ += len;
}

void Buffer::RetrieveUntil(const char* end) {
    assert(Peek() <= end );
    Retrieve(end - Peek());
}

void Buffer::RetrieveAll() { //初始化缓冲区
    bzero(&buffer_[0], buffer_.size());
    readPos_ = 0;
    writePos_ = 0;
}

std::string Buffer::RetrieveAllToStr() {
    std::string str(Peek(), ReadableBytes());
    RetrieveAll();
    return str;
}

const char* Buffer::BeginWriteConst() const { //获取写入起点，不可修改
    return BeginPtr_() + writePos_;
}

char* Buffer::BeginWrite() { //获取写入位置
    return BeginPtr_() + writePos_;
}

void Buffer::HasWritten(size_t len) {
    writePos_ += len;
} 

void Buffer::Append(const std::string& str) {
    Append(str.data(), str.length());
}

void Buffer::Append(const void* data, size_t len) {
    assert(data);
    Append(static_cast<const char*>(data), len);
}

void Buffer::Append(const char* str, size_t len) { 
    assert(str);
    EnsureWriteable(len); //确保能写
    std::copy(str, str + len, BeginWrite()); //写入
    HasWritten(len); //调整写入位置
}

void Buffer::Append(const Buffer& buff) {
    Append(buff.Peek(), buff.ReadableBytes());
}

void Buffer::EnsureWriteable(size_t len) { 
    if(WritableBytes() < len) {//当前buffer空间不够
        MakeSpace_(len);//扩容
    }
    assert(WritableBytes() >= len);
}

ssize_t Buffer::ReadFd(int fd, int* saveErrno) {
    char buff[65535]; //临时数组，保证把所有数据读出来
    struct iovec iov[2];
    const size_t writable = WritableBytes();
    // 分散读
    iov[0].iov_base = BeginPtr_() + writePos_;
    iov[0].iov_len = writable;
    iov[1].iov_base = buff;
    iov[1].iov_len = sizeof(buff);

    const ssize_t len = readv(fd, iov, 2);//分散读，获取读的总字节数len
    if(len < 0) { //读出错
        *saveErrno = errno; 
    }
    else if(static_cast<size_t>(len) <= writable) { //写得下
        writePos_ += len;
    }
    else { //buffer写不下
        writePos_ = buffer_.size();
        Append(buff, len - writable); //调整或扩容
    }
    return len;
}

ssize_t Buffer::WriteFd(int fd, int* saveErrno) {
    size_t readSize = ReadableBytes();
    ssize_t len = write(fd, Peek(), readSize);
    if(len < 0) {
        *saveErrno = errno;
        return len;
    } 
    readPos_ += len;
    return len;
}

char* Buffer::BeginPtr_() {
    return &*buffer_.begin();
}

const char* Buffer::BeginPtr_() const {
    return &*buffer_.begin();
}

void Buffer::MakeSpace_(size_t len) { 
    if(WritableBytes() + PrependableBytes() < len) { //写不下
        buffer_.resize(writePos_ + len + 1);
    } 
    else { //够写，调整即可
        size_t readable = ReadableBytes(); 
        std::copy(BeginPtr_() + readPos_, BeginPtr_() + writePos_, BeginPtr_()); 
        readPos_ = 0;
        writePos_ = readPos_ + readable;
        assert(readable == ReadableBytes());
    }
}